package javango.mojo;

import java.io.File;
import java.io.FileInputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;
import java.util.ArrayList;
import java.util.Properties;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

/**
 * Reset the database by dropping all tables and then recreating them.
 * 
 * @goal resetdb
 * @requiresDependencyResolution runtime
 * @execute phase="compile"
 * @description Runs the drop and create sqls against the database
 */
public class ResetDbMojo extends AbstractMojo
{
	
	/**
	 * <i>Maven Internal</i>: Project to interact with.
	 *
	 * @parameter expression="${project}"
	 * @required
	 * @readonly
	 * @noinspection UnusedDeclaration
	 */
	private MavenProject project;
	
	/**
     * The hibernate.properties file
     *
     * @parameter expression="${project.build.outputDirectory}/hibernate.properties"
     * @required
     *
     */
    private File hibernateProperties;
    
    /**
     * The hibernate.xml file
     *
     * @parameter expression="${project.build.outputDirectory}/hibernate.cfg.xml"
     * @required
     *
     */
    private File hibernateCfgXml;

    
    /**
     * @see org.apache.maven.plugin.Mojo#execute()
     */
    public void execute() throws MojoExecutionException, MojoFailureException
    {
    	Thread currentThread = Thread.currentThread();
    	ClassLoader oldClassLoader = currentThread.getContextClassLoader();

    	try
    	{
    		currentThread.setContextClassLoader( getClassLoader() );
   			doExecute();
    	}
    	finally
    	{
    		currentThread.setContextClassLoader( oldClassLoader );
    	}
    }
    
    public void doExecute() throws MojoExecutionException
    {
    	try {
	    	Properties props = new Properties();
	    	props.load(new FileInputStream(hibernateProperties));
	    	Configuration cfg = new AnnotationConfiguration().configure(hibernateCfgXml);
	    	cfg.setProperties(props);
		        getLog().info("Dropping all database tables.");
			new SchemaExport(cfg).drop(false, true);
			getLog().info("Done,  creating all database tables.");
			new SchemaExport(cfg).create(false, true);
			getLog().info("Done.");
    	} catch (Exception e) {
    		throw new MojoExecutionException(e.getMessage());
    	}
    }

    /**
     * Returns the an isolated classloader.
     *
     * @return ClassLoader
     * @noinspection unchecked
     */
    private ClassLoader getClassLoader()
    {
    	try
    	{
    		List classpathElements = new ArrayList(); 
    		classpathElements.add( project.getBuild().getOutputDirectory() );
    		URL urls[] = new URL[classpathElements.size()];
    		for ( int i = 0; i < classpathElements.size(); ++i )
    		{
    			urls[i] = new File( (String) classpathElements.get( i ) ).toURL();
    			System.out.println(urls[i].toString());
    		}
    		return new URLClassLoader( urls, this.getClass().getClassLoader() );
    	}
    	catch ( Exception e )
    	{
    		getLog().debug( "Couldn't get the classloader." );
    		return this.getClass().getClassLoader();
    	}
    }
}
